/*
 * not type checking this file because flow doesn't play well with
 * dynamically accessing methods on Array prototype
 */

import { def } from '../util/index';

const arrayProto = Array.prototype;
// 使用数组的原型创建一个新的对象
export const arrayMethods = Object.create(arrayProto);
// 修改数组元素的方法。这些方法会修改原始数组。
const methodsToPatch = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'];

/**
 * Intercept mutating methods and emit events
 */
methodsToPatch.forEach(function (method) {
    // cache original method
    // 保存数组原方法
    const original = arrayProto[method];
    // 调用 Object.defineProperty() 重新定义修改数组的方法
    def(arrayMethods, method, function mutator(...args) {
        // 执行数组的原始方法
        const result = original.apply(this, args);
        // 获取数组对象的 ob 对象
        const ob = this.__ob__;
        // 用来存储数组中新增的变量，push、unshift会将传入的参数存入inserted。splice 第3个参数值存入insterted中
        let inserted;
        switch (method) {
            case 'push':
            case 'unshift':
                inserted = args;
                break;
            case 'splice':
                inserted = args.slice(2);
                break;
        }
        // 对插入的新元素，重新遍历数组元素设置为响应式数据（遍历数组新增的元素，如果数组元素为对象，将对象设置为响应式）
        if (inserted) ob.observeArray(inserted);
        // notify change
        // 调用了修改数组的方法，调用数组的ob对象发送通知
        ob.dep.notify();
        return result;
    });
});
